﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

namespace WebkitIISHost.ReadCard
{
    public class WorKer
    {

        public static List<DrillDepthInfo> drillDepthInfoList = new List<DrillDepthInfo>(); // 钻孔测深二级目录内容
        public static List<DrillAngleInfo> drillAngleInfoList = new List<DrillAngleInfo>(); // 钻孔角度二级目录
        public static List<DrillData> DrillDataList = new List<DrillData>(); // 深度角度组合后的列表
        public static List<DrillOrbitInfo> drillOrbitInfoList = new List<DrillOrbitInfo>(); // 钻孔轨迹二级目录列表
        public static byte drive_index = 1;


        public string Drive_dir;
        public string Drive_Name;
        public string IsDataToText;


        public BackgroundWorker backgroundWorker;
        private bool isSuspend;
        delegate void SetTextCallback(CustomEventArgs e);
        public WorKer()
        {
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.WorkerSupportsCancellation = true;
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        }

        CustomEventArgs customEventArgs = new CustomEventArgs();
        /// <summary>
        /// 处理程序
        /// </summary>
        private bool StartOn()
        {
            #region"变量"
            int depthNum = -1;
            int angleNum = -1;
            string isThreadRunning = new string(new char[10]);
            string temp_buffer = new string(new char[8]);
            string str_SQL = "";
            string str_tableName = "";
            int total_data_num = 0; //
            int current_proc_num = 0;

            float currXAxis, currYAxis, currZAxis, prevXAxis, prevYAxis, prevZAxis, deltaXAxis, deltaYAxis, deltaZAxis, prevDepth, currDepth;
            string str_drill_index = new string(new char[20]);
            string str_temp = new string(new char[20]);

            #endregion

            drive_index = Convert.ToByte(Drive_dir);

            try
            {
                sd_Analysis.SDUtils = new SDUtils(Drive_Name);
                sd_Analysis.IsDataToText = IsDataToText;
            }
            catch (Exception ex)
            {
                MessageBox.Show("打开SD卡失败!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }

            List<DrillDepthRealData> depths = new List<DrillDepthRealData>();
            List<DrillAngleRealData> angles = new List<DrillAngleRealData>();

            if (sd_Analysis.getDrillHoleNum(500, ref depthNum) != 0 && sd_Analysis.getDrillHoleNum(2000000, ref angleNum) != 0)
            {
                int num = (depthNum > angleNum ? depthNum : angleNum);
                total_data_num = sd_Analysis.readDrillDepthInfo(ref drillDepthInfoList, depthNum);
                sd_Analysis.readDrillAngleInfo(ref drillAngleInfoList, angleNum);
                sd_Analysis.composeDirectorys(ref DrillDataList); //整合深度和角度数据

                //将密采数据写入到数据库
                DataType = "正在读取钻孔深度和角度数据";
                //DrillData it = new DrillData();

                for (int m = 0; m <= num; m++) //while (num >= 0) //((num >= 0) && it.MoveNext())
                {
                    DataCountNumber = num;
                    #region" 暂停"

                    if (backgroundWorker.CancellationPending)
                    {
                        customEventArgs.e = "停止";
                        return false;
                    }
                    //当需要暂停操作时，阻止后台线程继续执行
                    if (isSuspend)
                    {
                        customEventArgs.e = "暂停";
                        onSetText(customEventArgs);
                    }
                    while (isSuspend)
                    {
                        if (backgroundWorker.CancellationPending)
                        {
                            customEventArgs.e = "停止";
                            onSetText(customEventArgs);
                            return false;
                        }
                        System.Threading.Thread.Sleep(50);
                    }
                    backgroundWorker.ReportProgress(m);
                    customEventArgs.e = "开始";
                    backgroundWorker.ReportProgress(m);
                    customEventArgs.i = m;

                    onSetText(customEventArgs);
                    System.Threading.Thread.Sleep(100);

                    #endregion""

                    //深度扇区暂时不用，单独处理
                    #region 深度数据
                    try
                    {
                        DrillDepthInfo it = new DrillDepthInfo();
                        if (drillDepthInfoList.Count > m)
                        {
                            it = drillDepthInfoList[m];
                            DrillDepthRealData myDrillDepthRealData = new DrillDepthRealData();
                            byte[] depthBuffer = new byte[512];
                            int depthSavedGroupNums;

                            {
                                // 一个钻孔的数据
                                depthSavedGroupNums = it.savedGroupNums;

                                int j = it.dataStartSector;
                                int half_sector = 1;

                                currDepth = 0.0F;
                                currXAxis = currYAxis = currZAxis = 0.0F;
                                str_drill_index = new string(new char[20]);

                                // 生成钻孔字符串格式的钻孔编号
                                str_drill_index = string.Format("{0:D6}{1:D6}{2:D4}", it.drillNum.workPlace, it.drillNum.field, it.drillNum.drill);
                                // 检查数据库中是否存在钻孔的表名，如果不存在就创建一个。SD的密采数据单独放一个表中，以区分轨迹数据
                                str_tableName = "DrillHoleRun";
                                str_tableName += it.StartTime.ToString().Substring(0, 6);
                                sd_Analysis.check_table_exist(str_tableName.ToString(), str_drill_index);

                                for (int i = it.dataStartSector; i <= it.dataEndSector; ++i)
                                {
                                    // 读取一个深度数据扇区 -> 8条记录
                                    sd_Analysis.SDUtils.read_sectors(i, 1, 0, ref depthBuffer);
                                    // 读取半个角度数据扇区 -> 8条记录
                                    //sd_Analysis.SDUtils.read_sectors(j, 1, half_sector, ref angleBuffer);

                                    for (int k = 0; k <= 7 && depthSavedGroupNums > 0; k++)
                                    {
                                        byte[] b1 = new byte[64];
                                        Buffer.BlockCopy(depthBuffer, k * 64, b1, 0, 64);
                                        myDrillDepthRealData = sd_Analysis.getOneDepthData(b1);
                                        depthSavedGroupNums = (depthSavedGroupNums > 0) ? (depthSavedGroupNums - 1) : 0;

                                        //byte[] b2 = new byte[32];
                                        //Buffer.BlockCopy(depthBuffer, k * 32, b2, 0, 32);
                                        //myDrillAngleRealData = sd_Analysis.getOneAngleData(b2);
                                        //angleSavedGroupNums = (angleSavedGroupNums > 0) ? (angleSavedGroupNums - 1) : 0;

                                        // 处理三维坐标信息
                                        {
                                            prevDepth = currDepth;
                                            currDepth = myDrillDepthRealData.currDepth;

                                            prevXAxis = currXAxis;
                                            prevYAxis = currYAxis;
                                            prevZAxis = currZAxis;

                                            //deltaXAxis = (currDepth - prevDepth) * Convert.ToSingle(Math.Sin(myDrillAngleRealData.inclination));
                                            //deltaYAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Cos(myDrillAngleRealData.inclination) * Math.Cos(myDrillAngleRealData.azimuth));
                                            //deltaZAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Cos(myDrillAngleRealData.inclination) * Math.Sin(myDrillAngleRealData.azimuth));

                                            //currXAxis = prevXAxis + deltaXAxis;
                                            //currYAxis = prevYAxis + deltaYAxis;
                                            //currZAxis = prevZAxis + deltaZAxis;
                                        }

                                        //将密采数据写入到数据库

                                        myDrillDepthRealData.TableName = str_tableName;
                                        myDrillDepthRealData.DrillIndex = str_drill_index;
                                        depths.Add( myDrillDepthRealData);
//                                        str_SQL = sd_Analysis.CreateSQL_Depth_Angle();

                                        current_proc_num++;
                                    }

                                    if (half_sector == 0)
                                        half_sector++;
                                    else
                                    {
                                        half_sector = 0;
                                        j++;
                                    }
                                }

                            }

                        }
                    }
                    catch (Exception ex)
                    {
//                        SystemConfig.WriteLog("角度::" + ex.Message);
                    }
                    #endregion

                    #region" 角度数据"

                    try
                    {
                        //it = DrillDataList[m];
                        DrillAngleInfo it = new DrillAngleInfo();
                        if (drillAngleInfoList.Count > m)
                        {
                            it = drillAngleInfoList[m];
                            string StartTime = sd_Analysis.BCDToString(it.StartTime).Replace("-", "");
                            StartTime = (StartTime.Length >= 6 ? StartTime.Substring(0, 6) : StartTime);

                            sd_Analysis.CreateSQL_DrillHoleInfo(it, StartTime);

                            DrillAngleRealData myDrillAngleRealData = new DrillAngleRealData();
                            byte[] angleBuffer = new byte[512];
                            int angleSavedGroupNums;
                            {
                                // 一个钻孔的数据
                                angleSavedGroupNums = it.savedGroupNums;
                                int j = it.dataStartSector;
                                int half_sector = 1;

                                currDepth = 0.0F;
                                currXAxis = currYAxis = currZAxis = 0.0F;
                                str_drill_index = new string(new char[20]);

                                float alpha = 0F;

                                // 生成钻孔字符串格式的钻孔编号
                                str_drill_index = string.Format("{0:D6}{1:D6}{2:D4}", it.drillNum.workPlace, it.drillNum.field, it.drillNum.drill);
                                // 检查数据库中是否存在钻孔的表名，如果不存在就创建一个。SD的密采数据单独放一个表中，以区分轨迹数据
                                str_tableName = "DrillHoleRun";
                                str_tableName += StartTime;
                                sd_Analysis.check_table_exist(str_tableName.ToString(), str_drill_index);
                                sd_Analysis.check_drill_info(it, str_drill_index);

                                for (int i = it.dataStartSector; i <= it.dataEndSector; ++i)
                                {
                                    //// 读取一个深度数据扇区 -> 8条记录
                                    //sd_Analysis.SDUtils.read_sectors(i, 1, 0, ref depthBuffer);
                                    // 读取半个角度数据扇区 -> 8条记录
                                    //sd_Analysis.SDUtils.read_sectors(j, 1, half_sector, ref angleBuffer);

                                    sd_Analysis.SDUtils.read_sectors(j, 1, 0, ref angleBuffer);
                                    for (int k = 0; k <= 15 && angleSavedGroupNums > 0; k++)
                                    {
                                        //byte[] b1 = new byte[64];
                                        //Buffer.BlockCopy(depthBuffer, k * 64, b1, 0, 64);
                                        //myDrillDepthRealData = sd_Analysis.getOneDepthData(b1);
                                        //depthSavedGroupNums = (depthSavedGroupNums > 0) ? (depthSavedGroupNums - 1) : 0;

                                        byte[] b2 = new byte[32];
                                        Buffer.BlockCopy(angleBuffer, k * 32, b2, 0, 32);
                                        myDrillAngleRealData = sd_Analysis.getOneAngleData(b2);
                                        angleSavedGroupNums = (angleSavedGroupNums > 0) ? (angleSavedGroupNums - 1) : 0;

                                        if (myDrillAngleRealData.currDepth != (float)9999.99) //深度：0.00~9999.99，BCD码表示，占用3个字节，小数点后2位。（9999.99表示该组数据无效）。
                                        {
                                            alpha = Convert.ToSingle(myDrillAngleRealData.inclination / 180 * Math.PI);
                                            float beta = Convert.ToSingle(myDrillAngleRealData.azimuth / 180 * Math.PI);

                                            // 处理三维坐标信息
                                            prevDepth = currDepth;
                                            currDepth = myDrillAngleRealData.currDepth;

                                            prevXAxis = currXAxis;
                                            prevYAxis = currYAxis;
                                            prevZAxis = currZAxis;

                                            //deltaXAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Cos(-beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                            //deltaYAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(-beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                            //deltaZAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(alpha), 2));

                                            deltaXAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                            deltaYAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Cos(-beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                            deltaZAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(alpha), 2));

                                            currXAxis = (float)Math.Round(prevXAxis + deltaXAxis, 4);
                                            currYAxis = (float)Math.Round(prevYAxis + deltaYAxis, 4);
                                            currZAxis = (float)Math.Round(prevZAxis + deltaZAxis, 4);

                                            //将密采数据写入到数据库

                                            myDrillAngleRealData.TableName = str_tableName;
                                            myDrillAngleRealData.DrillIndex = str_drill_index;
                                            myDrillAngleRealData.XAxis = currXAxis;
                                            myDrillAngleRealData.YAxis = currYAxis;
                                            myDrillAngleRealData.ZAxis = currZAxis;
                                            angles.Add(myDrillAngleRealData);
//                                            str_SQL = sd_Analysis.CreateSQL_Angle(str_tableName, str_drill_index, myDrillAngleRealData, currXAxis, currYAxis, currZAxis);
                                        }

                                        current_proc_num++;
                                    }

                                    j++;

                                    //if (half_sector == 0)
                                    //    half_sector++;
                                    //else
                                    //{
                                    //    half_sector = 0;
                                    //    j++;
                                    //}
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
//                        SystemConfig.WriteLog("角度::" + ex.Message);
                    }
                    #endregion

                }
            }

            //读取钻孔轨迹数据 根据方案 20140328 删除轨迹扇区处理， 轨迹合并到角度扇区
            //Readorbit();


            sd_Analysis.CreateSQL_Depth_Angle(depths);
            sd_Analysis.CreateSQL_Angle(angles);


            customEventArgs.e = "完成";
            onSetText(customEventArgs);
            DataType = "完成";

            return true;
        }

        public string DataType;
        public int DataCountNumber;

        public void Readorbit()
        {
            DataType = "正在读取钻孔轨迹数据";

            float currXAxis, currYAxis, currZAxis, prevXAxis, prevYAxis, prevZAxis, deltaXAxis, deltaYAxis, deltaZAxis, prevDepth, currDepth;
            string str_SQL;
            /////////////////////////////////////////////////////////////////////////////////////////////////
            //钻孔深度和钻孔角度数据读取完毕，开始读取钻孔轨迹数据
            int orbitHoleNum = 0;

            if (sd_Analysis.getDrillHoleNum(3000000, ref orbitHoleNum) == 0)
            {
                sd_Analysis.exitConnect();
                return;
            }

            drillOrbitInfoList.Clear();

            int total_data_num = sd_Analysis.readDrillOrbitInfo(ref drillOrbitInfoList, orbitHoleNum);
            int current_proc_num = 0;

            //读取轨迹数据，并将轨迹数据写到数据库
            DrillOrbitInfo orbit_it;
            if (orbitHoleNum >= 0)
            {
                DataCountNumber = drillOrbitInfoList.Count;

                List<DrillOrbitRealData> orbitRealDatas = new List<DrillOrbitRealData>();
                for (int orbit_it_index = 0; orbit_it_index < drillOrbitInfoList.Count; orbit_it_index++)
                {
                    #region" 暂停"
                    if (backgroundWorker.CancellationPending)
                    {
                        customEventArgs.e = "停止";
                        return;
                    }
                    //当需要暂停操作时，阻止后台线程继续执行
                    if (isSuspend)
                    {
                        customEventArgs.e = "暂停";
                        onSetText(customEventArgs);
                    }
                    while (isSuspend)
                    {
                        if (backgroundWorker.CancellationPending)
                        {
                            customEventArgs.e = "停止";
                            onSetText(customEventArgs);
                            return;
                        }
                        System.Threading.Thread.Sleep(50);
                    }
                    backgroundWorker.ReportProgress(orbit_it_index + 1);
                    customEventArgs.e = "开始";
                    backgroundWorker.ReportProgress(orbit_it_index + 1);
                    customEventArgs.i = orbit_it_index + 1;

                    onSetText(customEventArgs);
                    System.Threading.Thread.Sleep(100);

                    #endregion""

                    orbit_it = drillOrbitInfoList[orbit_it_index];

                    #region "读取一个钻孔到表"

                    try
                    {
                        DrillOrbitRealData myDrillOrbitRealData = new DrillOrbitRealData();
                        byte[] orbitBuffer = new byte[512];
                        int orbitSavedGroupNums = orbit_it.savedGroupNums;

                        currDepth = 0.0F;
                        currXAxis = currYAxis = currZAxis = 0.0F;

                        float alpha = 0F;

                        // 生成钻孔字符串格式的钻孔编号
                        string str_drill_index = string.Format("{0:D6}{1:D6}{2:D4}", orbit_it.drillNum.workPlace, orbit_it.drillNum.field, orbit_it.drillNum.drill);
                        // 检查数据库中是否存在钻孔的表名，如果不存在就创建一个。SD的密采数据单独放一个表中，以区分轨迹数据
                        string str_tableName = "DrillHoleRun";
                        str_tableName += str_drill_index;
                        sd_Analysis.check_table_exist(str_tableName.ToString(), str_drill_index);

                        for (int i = orbit_it.dataStartSector; i <= orbit_it.dataEndSector; i++)
                        {
                            //读取一个深度数据扇区 -> 16条记录                        
                            sd_Analysis.SDUtils.read_sectors(i, 1, 0, ref orbitBuffer);

                            //根据orbitDataPiece和当前orbitSavedGroupNums生成进度条
                            for (int k = 0; k < 16 && orbitSavedGroupNums > 0; k++)
                            {
                                byte[] orbitBuffer_t = new byte[32];
                                Buffer.BlockCopy(orbitBuffer, k * 32, orbitBuffer_t, 0, 32);

                                myDrillOrbitRealData = sd_Analysis.getOneOrbitData(orbitBuffer_t); //orbitBuffer_t+k*32
                                orbitSavedGroupNums = (orbitSavedGroupNums > 0) ? (orbitSavedGroupNums - 1) : 0;


                                alpha = Convert.ToSingle(
                                myDrillOrbitRealData.inclination / 180 * Math.PI);
                                float beta = Convert.ToSingle(myDrillOrbitRealData.azimuth / 180 * Math.PI);

                                // 处理三维坐标信息
                                {
                                    prevDepth = currDepth;
                                    currDepth = myDrillOrbitRealData.cur_depth;

                                    prevXAxis = currXAxis;
                                    prevYAxis = currYAxis;
                                    prevZAxis = currZAxis;

                                    //deltaXAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Cos(-beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                    //deltaYAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(-beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                    //deltaZAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(alpha), 2));

                                    deltaXAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                    deltaYAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Cos(-beta), 2) * Math.Round(Math.Cos(alpha), 2));
                                    deltaZAxis = Convert.ToSingle((currDepth - prevDepth) * Math.Round(Math.Sin(alpha), 2));

                                    currXAxis = prevXAxis + deltaXAxis;
                                    currYAxis = prevYAxis + deltaYAxis;
                                    currZAxis = prevZAxis + deltaZAxis;
                                }

                                //将密采数据写入到数据库
                                myDrillOrbitRealData.TableName = str_tableName;
                                myDrillOrbitRealData.DrillIndex = str_drill_index;
                                myDrillOrbitRealData.XAxis = currXAxis;
                                myDrillOrbitRealData.YAxis = currYAxis;
                                myDrillOrbitRealData.ZAxis = currZAxis;
                                orbitRealDatas.Add(myDrillOrbitRealData);
//                                str_SQL = sd_Analysis.CreateSQL_Orbit(str_tableName, str_drill_index, myDrillOrbitRealData, currXAxis, currYAxis, currZAxis);
                                current_proc_num++;
                            }
                            //生成进度
                            //(current_proc_num /total_data_num)
                        }
                    }
                    catch (Exception ex)
                    {
//                        SystemConfig.WriteLog("钻孔轨迹::" + ex.Message);
                    }
                    #endregion ""

                }
            }
        }

        public void Start()
        {
            backgroundWorker.RunWorkerAsync();
        }

        public void Suspend()
        {
            isSuspend = true;
        }
        public void Continue()
        {
            isSuspend = false;
        }
        public void Stop()
        {
            backgroundWorker.CancelAsync();
        }

        bool DoWorkRes = false;
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            DoWorkRes = StartOn();
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            customEventArgs.p = e.ProgressPercentage;
            onProgress(customEventArgs);
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            onSetText(customEventArgs);

            if (DoWorkRes)
                MessageBox.Show("读取数据完毕！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        public delegate void SetTextEventHandler(object sender, CustomEventArgs e);
        public event SetTextEventHandler SetText;
        protected virtual void onSetText(CustomEventArgs e)
        {
            if (SetText != null)
            {
                SetText(this, e);
            }
        }
        public delegate void ProgressEventHandler(object sender, CustomEventArgs e);
        public event ProgressEventHandler Progress;
        protected virtual void onProgress(CustomEventArgs e)
        {
            if (Progress != null)
            {
                Progress(this, e);
            }
        }
    }
    public class CustomEventArgs : EventArgs
    {
        public CustomEventArgs() { }
        public string e { set; get; }
        public int p { set; get; }
        public int i { set; get; }
    }

  
}